<template>
  <div class="recipient-select-panel">
    <div>
      <el-input v-model="keyword" suffix-icon="el-icon-search" :placeholder="$t('loc.search')"/>
    </div>
    <recipient-loading :loading="loading"/>
    <div v-show="!loading" style="height: calc(100% - 60px)">
      <!-- 搜索结果树 -->
      <el-tree class="tree-search scrollbar-new"
               v-show="showSearch"
               :data="searchResults"
               :props="treeDataProps"
               show-checkbox
               :expand-on-click-node="false"
               :check-on-click-node="true"
               node-key="treeNodeKey"
               ref="searchTree"
               @check-change="treeCheckChangeHandler"
               @check="handleCheck">
          <template #default="{ node, data }" style="line-height: 48px;">
            <el-avatar :src="data.avatarUrl"></el-avatar>
            <span> {{ data.treeLabel }}</span>
          </template>
      </el-tree>
      <!-- 筛选树 -->
      <div v-show="!showSearch" style="height: 100%;">
        <!-- 全选/取消 -->
        <el-checkbox v-model="checkAll" @change="handleCheckAllChange">
          {{ $t('loc.allStf') }}
        </el-checkbox>
        <!-- 分割线 -->
        <el-divider/>
        <!-- 树 -->
        <el-tree class="tree-normal scrollbar-new"
                 :props="treeDataProps"
                 :load="loadNode"
                 lazy show-checkbox
                 ref="tree"
                 :expand-on-click-node="false"
                 :check-on-click-node="true"
                 node-key="treeNodeKey"
                 :empty-text="$t('loc.nostaff')"
                 @check-change="treeCheckChangeHandler"
                 @check="handleCheck">
          <template #default="{ node, data }"
                    :title="data.tips"
                    :style="{'line-height':data.nodeDataType === 'staff' ? '48px' : '36px'}">
            <el-avatar :src="data.avatarUrl" size="medium" v-if="data.nodeDataType === 'staff'"></el-avatar>
            <span> {{ data.treeLabel }}</span>
          </template>
        </el-tree>
      </div>
    </div>
  </div>
</template>
<script>
import {deepEqual} from "@/utils/common";
import MessageAPI from '@/api/message';
import RecipientLoading from "@/views/modules/message/MessageCreate/Recipient/RecipientLoading";

export default {
  name: "RecipientSelectStaffPanel",
  components: {RecipientLoading},
  props: [
    'recipient', // 已选接收人
    'labels', // 已选接收人标签
  ],
  data() {
    return {
      keyword: '', // 搜索关键字
      searchResults: null, // 搜索结果
      showSearch: false, // 是否展示搜索结果
      checkAll: false, // 是否选中全部
      loading: false, // 根节点加载中
      treeDataProps: { // 树配置
        label: 'treeLabel',
        children: 'treeChildren',
        isLeaf: 'treeIsLeaf'
      },
      searchTimeOut: null, // 搜索限流
      rootsData: [], // 筛选树一层节点数据
    }
  },
  watch: {
    keyword(keyword) {
      this.searchTimeOut && clearTimeout(this.searchTimeOut);
      this.searchTimeOut = setTimeout(() => {
        // 清除关键字时，进入筛选状态
        if (!keyword || !keyword.trim() && this.showSearch) {
          this.showSearch = false;
          this.$refs.searchTree.setCheckedKeys([]);
          return;
        }
        keyword = keyword.trim();
        // 输入小于2个字符时，不予搜索
        if (keyword.length < 2) {
          return;
        }
        // 清空筛选树并隐藏
        this.$refs.tree.setCheckedKeys([]);
        this.checkAll = false;
        this.showSearch = true;
        // 进行搜索
        this.loading = true;
        MessageAPI.searchStaff(keyword).then(searchResults => {
          this.searchResults = (searchResults || []).map(staff => {
            return {
              ...staff,
              nodeDataType: 'staff',
              treeLabel: staff.displayName,
              treeNodeKey: staff.id,
              treeIsLeaf: true
            }
          });
          // 加载状态延迟关闭
          setTimeout(() => this.loading = false, 200);
        })
      }, 600);
    },
    labels(labels) {
      let {labels: currentTreeLabels} = this.calculateTreeValue();
      let labelIds = (labels || []).map(label => label.id);
      let unCheckLabels = currentTreeLabels.filter(label => !labelIds.includes(label.id));
      // 只处理删除情形
      if (unCheckLabels.length === 1) {
        let treeNodeKey = unCheckLabels[0].id;
        let tree = this.showSearch ? this.$refs.searchTree : this.$refs.tree;
        if (treeNodeKey === '00000000-0000-0000-0000-000000000000') {
          tree.setCheckedKeys([]);
        } else {
          let labels = [...unCheckLabels];
          unCheckLabels[0].variants && labels.push(...unCheckLabels[0].variants);
          labels.forEach(label => {
            tree.setChecked(label.id, false, true);
          })
        }
      }
    }
  },
  methods: {
    // 筛选树加载子节点
    loadNode(node, resolve) {
      let {data = {}, level} = node;
      let {treeNodeKey, nodeDataType} = data;
      // 加载一层节点时，显示加载中
      if (level === 0) {
        this.loading = true;
      }
      // 分组节点，数据已加载
      if (nodeDataType === 'composition') {
        resolve(node.data.children || []);
        return;
      }
      // 加载数据，并转换为树节点数据
      if (level === 0) {
        MessageAPI.listCentersOrGroups().then(({agencyAdmins = [], list = []}) => {
          let agencyAdminNodes = agencyAdmins.map(agencyAdmin => {
            return {
              ...agencyAdmin,
              nodeDataType: 'staff',
              treeLabel: agencyAdmin.displayName,
              treeNodeKey: agencyAdmin.id,
              treeIsLeaf: true
            }
          });
          let centerNodes = list.map(center => {
            let {name, id, hasStaff} = center;
            return {
              ...center,
              nodeDataType: 'center',
              treeLabel: name,
              treeNodeKey: id,
              // treeIsLeaf: !hasStaff,
              treeIsLeaf: false,
              // disabled: !hasStaff,
              disabled: false,
              tips: !hasStaff ? this.$t('loc.nostaff') : ''
            }
          });
          this.rootsData = agencyAdminNodes.concat(centerNodes);
          resolve(this.rootsData);
          // 加载状态延迟关闭
          setTimeout(() => this.loading = false, 200);
        })
      } else {
        MessageAPI.listCenterUsers(treeNodeKey).then(({id, siteAdmins = [], teachers = []}) => {
          let result = [];
          siteAdmins.length && result.push({
            nodeDataType: 'composition',
            treeLabel: this.$t('loc.allSIteAdmin'),
            treeNodeKey: id + "_admin",
            treeIsLeaf: false,
            children: siteAdmins.map(siteAdmin => ({
              ...siteAdmin,
              nodeDataType: 'staff',
              treeLabel: siteAdmin.displayName,
              treeNodeKey: `${treeNodeKey},${siteAdmin.id}`,
              treeIsLeaf: true
            }))
          });
          teachers.length && result.push({
            nodeDataType: 'composition',
            treeLabel: this.$t('loc.allTher'),
            treeNodeKey: id + "_teacher",
            treeIsLeaf: false,
            children: teachers.map(teacher => ({
              ...teacher,
              nodeDataType: 'staff',
              treeLabel: teacher.displayName,
              treeNodeKey: `${treeNodeKey},${teacher.id}`,
              treeIsLeaf: true
            }))
          });
          resolve(result);
        })
      }
    },
    // 全选/取消全选 点击事件处理器
    handleCheckAllChange(checked) {
      let nodes = checked ? this.rootsData.filter(item => !item.disabled) : [];
      this.$refs.tree.setCheckedNodes(nodes);
      this.handleCheck();
    },
    // 树变更处理
    treeCheckChangeHandler() {
      let tree = this.showSearch ? this.$refs.searchTree : this.$refs.tree;
      // 筛选树状态同步到全选按钮
      !this.showSearch && (this.checkAll = this.rootsData.every(nodeData => {
        let node = tree.getNode(nodeData);
        return node && (node.checked || node.disabled);
      }));
      // 向外同步状态
      let {recipient, labels} = this.calculateTreeValue();
      if (!deepEqual(recipient, this.recipient)) {
        console.log('向外同步状态', recipient,labels);
        this.$emit('update:recipient', recipient);
        this.$emit('update:labels', labels);
      }
    },
    // 计算当前状态下树的值
    calculateTreeValue() {
      let result = {
        recipient: {
          centerIds: [],
          staffIds: [],
        },
        labels: []
      }
      if (this.checkAll) {
        this.rootsData.forEach(nodeData => {
          let {nodeDataType, treeNodeKey, disabled} = nodeData;
          if (nodeDataType === 'center' && !disabled) {
            result.recipient.centerIds.push(treeNodeKey);
          } else if (nodeDataType === 'staff') {
            result.recipient.staffIds.push(treeNodeKey);
          }
        })
        result.labels.push({id: '00000000-0000-0000-0000-000000000000', name: "all_staff"})
        return result;
      }
      let tree = this.showSearch ? this.$refs.searchTree : this.$refs.tree;
      let nodes = tree.getCheckedNodes();
      nodes.forEach(nodeData => {
        let node = tree.getNode(nodeData);
        let {centerIds = [], staffIds = [], label} = this.calculateNodeValue(node) || {};
        result.recipient.centerIds.push(...centerIds);
        result.recipient.staffIds.push(...staffIds);
        this.mergeLabels(result.labels, label);
      });
      console.log(result)
      return result;
    },
    // 标签合并
    mergeLabels(labels, label) {
      // 无标签，忽略
      if (!label) {
        return;
      }
      // 不存在，直接添加
      let exist = labels.find(item => this.isSameLabel(label, item));
      if (!exist) {
        labels.push(label);
        return;
      }
      // 已存在，放入 variants 字段中
      exist.variants = exist.variants || [];
      exist.variants.push(label);
    },
    // 判断两个标签是否相同
    isSameLabel({id}, label) {
      return label.id.split(',').slice(-1)[0] === id.split(',').slice(-1)[0];
    },
    // 计算树节点的值
    calculateNodeValue(node) {
      // 上级节点被选中，则不计算
      if (node.parent.checked) {
        return;
      }
      let {nodeDataType, treeNodeKey, treeLabel, disabled} = node.data;
      // 员工节点
      if (nodeDataType === 'staff') {
        return {
          staffIds: treeNodeKey.split(",").slice(-1),
          label: {id: treeNodeKey, name: treeLabel}
        }
      }
      // 幼儿园节点
      if (nodeDataType === 'center') {
        return {
          centerIds: !disabled && [treeNodeKey] || [],
          label: {id: treeNodeKey, name: `${treeLabel}_all_staff`}
        }
      }
      // 园长组合节点
      if (nodeDataType === 'composition' && treeNodeKey.endsWith('_admin')) {
        return {
          staffIds: node.data.children.map(staff => staff.id),
          label: {id: treeNodeKey, name: `${node.parent.data.treeLabel}_all_siteAdmin_staff`}
        }
      }
      // 教师组合节点
      if (nodeDataType === 'composition' && treeNodeKey.endsWith('_teacher')) {
        return {
          staffIds: node.data.children.map(staff => staff.id),
          label: {id: treeNodeKey, name: `${node.parent.data.treeLabel}_all_teacher_staff`}
        }
      }
    },
    reset() {
      let tree = this.showSearch ? this.$refs.searchTree : this.$refs.tree;
      tree.setCheckedNodes([])
    },
    handleCheck() {
      this.$emit('check')
    },
    getChecks () {
      return this.$refs.tree.getCheckedKeys()
    },
    setChecks (checks) {
      this.$refs.tree.setCheckedKeys(checks)
    }
  }
}
</script>

<style scoped lang="less">
.recipient-select-panel {
  display: flex;
  flex-flow: column;
  gap: 10px;
}

.el-divider {
  margin: 5px 0
}

.el-tree /deep/ & {
  .el-tree-node__content {
    height: auto;
    gap: 8px;

    & > .el-tree-node__expand-icon {
      padding: 0;
      font-size: 16px;
    }

    & > .el-checkbox {
      margin: 0;

      .el-checkbox__inner {
        width: 16px;
        height: 16px;
      }
    }

    & > .el-tree-node__label {
      font-size: 16px;
    }
  }
}

.el-checkbox /deep/ & {
  .el-checkbox__inner {
    width: 16px;
    height: 16px;
  }
}

.el-avatar {
  vertical-align: middle;
}

.el-tree {
  color: #303133;
}

.tree-search {
  max-height: 100%;
  overflow-y: auto;
}

.tree-normal {
  max-height: calc(100% - 40px);
  overflow-y: auto;
}
</style>